package com.mingliqiye.minecraft.enchantment.conflict.fabric.network;

import static com.mingliqiye.minecraft.enchantment.conflict.common.MinecraftMod.MOD_ID;

import com.google.gson.Gson;
import com.mingliqiye.minecraft.enchantment.conflict.common.ConfigManager;
import com.mingliqiye.minecraft.enchantment.conflict.common.ConfigPair;
import com.mingliqiye.minecraft.enchantment.conflict.fabric.FabricMod;
import com.mojang.logging.LogUtils;
import java.util.Map;
import net.fabricmc.fabric.api.client.networking.v1.ClientPlayNetworking;
import net.fabricmc.fabric.api.networking.v1.PayloadTypeRegistry;
import net.fabricmc.fabric.api.networking.v1.ServerPlayNetworking;
import net.minecraft.network.FriendlyByteBuf;
import net.minecraft.network.codec.StreamCodec;
import net.minecraft.network.protocol.common.custom.CustomPacketPayload;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.level.ServerPlayer;
import org.slf4j.Logger;

public record ConfigPayload(Map<String, ConfigPair> data) implements CustomPacketPayload {
    private static final Logger LOGGER = LogUtils.getLogger();
    public static final CustomPacketPayload.Type<ConfigPayload> TYPE = new CustomPacketPayload.Type<>(
        ResourceLocation.tryBuild(MOD_ID, "config_packet")
    );

    public static final StreamCodec<FriendlyByteBuf, ConfigPayload> CODEC = StreamCodec.of(
        (buf, payload) -> buf.writeUtf(ConfigManager.toyaml(payload.data())),
        (buf) -> new ConfigPayload(ConfigManager.fromyaml(buf.readUtf()))
    );

    public static void initializeClient() {
        ClientPlayNetworking.registerGlobalReceiver(TYPE, (payload, ctx) -> {
            ctx
                .client()
                .execute(() -> {
                    FabricMod.CONFIGMANAGER.setConfig(payload.data());
                    LOGGER.info("Load Server {} config {}", MOD_ID, payload.data());
                });
        });
    }

    public static void initializeServer() {
        PayloadTypeRegistry.playS2C().register(TYPE, CODEC);
    }

    public static void sendToPlayer(ServerPlayer player) {
        if (ServerPlayNetworking.canSend(player, TYPE)) {
            ServerPlayNetworking.send(player, new ConfigPayload(FabricMod.CONFIGMANAGER.getConfig()));
            LOGGER.info("Send {} config to player({}) ok", MOD_ID, player.getName().getString());
        } else {
            LOGGER.error("Cannot send config to {}: channel not registered", player.getName());
        }
    }

    public static void sendConfigToAllClient() {
        FabricMod.SERVER.getPlayerList().getPlayers().forEach(ConfigPayload::sendToPlayer);
    }

    @Override
    public Type<? extends CustomPacketPayload> type() {
        return TYPE;
    }
}
